import requests
import json
import os
import csv
import time
from typing import List, Dict
from openpyxl import Workbook
from openpyxl import load_workbook
from openpyxl.styles import numbers
from pymongo.errors import DuplicateKeyError
import pymongo
MONTHID="202508"
mongo_client = pymongo.MongoClient(host="mongodb://localhost:27017/",
    maxPoolSize=10,   # 最大连接数
    minPoolSize=5)
target_db = mongo_client["shouzhidaogua"]  # 读取的数据库名
target_collection = target_db[f"encrypted_response_body_{MONTHID}"]  # 读取的集合名
def h(t):
    """
    处理字符串类型的t，分割后解密拼接，最终解析为JSON
    :param t: 字符串类型的输入数据（对应原JS中的t.data为字符串的情况）
    :return: 解析后的JSON对象或原始数据
    """
    # 确保输入t是字符串类型（对应原逻辑的"string" == typeof t.data）
    if isinstance(t, str):
        # 按逗号分割字符串
        e = t.split(',')
        n = ""
        # 如果分割后有内容
        if len(e) > 0:
            # 遍历分割后的每一项（模拟JS的for...of循环）
            for a in e:
                # 调用已实现的p.decrypt解密，拼接结果
                n += p_decrypt(a)
        # 将拼接后的字符串解析为JSON并返回
        return json.loads(n)
    # 如果t不是字符串，直接返回原始数据
    return t
def p_decrypt(txt):
    '''
    网页js注入websocket服务端代码，
    同作用域内调用p.decrypt解密，
    本地开ws客户端，
    开flask连接服务端，
    发post请求返回解密结果字符串
    '''
    #txt='EOij0pyefzP6Zb4LvUNEWAP/p6ADr9MtIbrLjip6mGoSXRYLODMTaylBQFGcIYll8CUGKgdMaKmfHlxFuziRnUyLWQa6e0dvrIKPJ0QE9ExEUsm4zuuNH6Xi2XnNQR6AAQhJTt+o5m+w51t5Fi5V9Kg5gOvL07T7FBDmq+ULgI8='
    #print(f"待处理字符串长度: {len(txt)} 字符")
    res=requests.post("http://127.0.0.1:80",data={"encrypt_txt":txt})
    #print(res.text) 大量io，会影响性能
    return res.text
def test_process_full_txt():
    '''
    测试处理一个txt
    '''
    txt=read_txt_as_string(r'C:\Users\MECHREVO\PycharmProjects\spider_caohuijie\test_full_txt.txt')
    processed=h(txt)
    print(processed)
    return processed
def process_raw_response(str) -> Dict:
    processed=h(str)
    # 处理每个响应体
    print(processed)# 打印处理后的结果
    return processed            
def read_txt_as_string(file_path):
    """
    读取txt文件内容并返回一个完整字符串
    :param file_path: txt文件路径
    :return: 文件内容字符串（若文件不存在或出错则返回空字符串）
    """
    try:
        # 打开文件，指定编码（如utf-8，根据实际文件编码调整）
        with open(file_path, 'r', encoding='gbk') as file:
            # 读取全部内容为一个字符串
            content = file.read()
            return content
    except FileNotFoundError:
        print(f"错误：文件 '{file_path}' 不存在")
        return ""
    except UnicodeDecodeError:
        print(f"错误：文件 '{file_path}' 编码不是utf-8，请检查编码格式")
        return ""
    except Exception as e:
        print(f"读取文件时出错：{str(e)}")
        return ""
def process_json_and_insert(json_data: Dict, file_path: str = f"{MONTHID}_站点清单(新).xlsx") -> None:
    """
    处理JSON数据并插入到XLSX表格中，自动创建表头（若不存在）或追加数据（若表头已存在）
    长数字将以文本格式存储，避免科学计数法问题
    
    :param json_data: 输入的JSON数据（字典格式）
    :param file_path: 表格文件路径（默认"data_table.xlsx"）
    """
    # 提取records数据（核心数据部分）
    records = json_data.get("data", {}).get("records", [])
    if not records:
        print("警告：未找到有效记录（records为空），不执行插入操作")
        return

    # 1. 收集所有字段（表头）：确保包含所有记录中的键，避免字段缺失
    all_fields = set()
    for record in records:
        all_fields.update(record.keys())  # 收集所有出现过的键
    # 按第一个记录的字段顺序排序，剩余字段追加在后面（保证顺序一致性）
    first_record_fields = list(records[0].keys())
    remaining_fields = [field for field in all_fields if field not in first_record_fields]
    header = first_record_fields + remaining_fields  # 最终表头

    # 2. 检查文件是否存在，决定是否需要创建工作簿或加载现有工作簿
    file_exists = os.path.exists(file_path)
    
    if file_exists:
        # 加载现有工作簿
        wb = load_workbook(file_path)
        ws = wb.active  # 获取活动工作表
        # 检查现有表头是否与新表头一致
        existing_header = [cell.value for cell in ws[1]] if ws.max_row > 0 else []
        
        if existing_header != header:
            print("警告：现有表格表头与新数据表头不一致，将创建新的工作表")
            ws = wb.create_sheet(title=f"Data_{len(wb.sheetnames)}")
            # 写入新表头
            for col, field in enumerate(header, 1):
                ws.cell(row=1, column=col, value=field)
            start_row = 2
        else:
            start_row = ws.max_row + 1  # 从最后一行的下一行开始写入
    else:
        # 创建新工作簿
        wb = Workbook()
        ws = wb.active
        ws.title = "Data"  # 重命名工作表
        # 写入表头
        for col, field in enumerate(header, 1):
            ws.cell(row=1, column=col, value=field)
        start_row = 2
        print(f"已创建新表格，表头字段数：{len(header)}")

    # 3. 写入数据
    for row_idx, record in enumerate(records, start_row):
        for col_idx, field in enumerate(header, 1):
            value = record.get(field, "")
            
            # 处理空值
            if value is None:
                value = ""
                
            # 处理长数字：如果是数字且长度超过15位，以文本形式存储
            if isinstance(value, (int, float)) or (isinstance(value, str) and value.isdigit()):
                str_value = str(value)
                if len(str_value) > 15:
                    # 以文本格式存储长数字
                    ws.cell(row=row_idx, column=col_idx).number_format = numbers.FORMAT_TEXT
                    ws.cell(row=row_idx, column=col_idx, value=str_value)
                else:
                    ws.cell(row=row_idx, column=col_idx, value=value)
            else:
                ws.cell(row=row_idx, column=col_idx, value=value)

    # 保存工作簿
    wb.save(file_path)
    print(f"成功插入 {len(records)} 条数据到 {file_path}")
if __name__ == "__main__":
    beg=time.time()
    # 测试处理一个完整的txt文件
    #test_process_full_txt()
    # 测试处理单个字符串
    
    # decrypted_dict=test_process_full_txt()
    # process_json_and_insert(decrypted_dict)
    # end=time.time()
    # print(f"总耗时: {end - beg:.2f}秒")
    #raw_resp_documents=list(target_collection.find({})) 
    raw_resp_documents=list(target_collection.find({'page': {'$gt': 315}}))  # 从MongoDB读取数据)
    payment_list=[x.get('response_body') for x in raw_resp_documents]
    for i, raw_resp in enumerate(payment_list):
        print(f"正在处理第 {i+1} 条响应体...")
        processed_response = process_raw_response(raw_resp)
        process_json_and_insert(processed_response)
    end=time.time()
    print(f"总耗时: {end - beg:.2f}秒")
    # 处理完毕，所有数据已插入到指定的Excel文件中